#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>

// 定义超级块结构体
struct ext_super_block {
    uint32_t s_inodes_count;        
    uint32_t s_blocks_count;        
    uint32_t s_r_blocks_count;      
    uint32_t s_free_blocks_count;   
    uint32_t s_free_inodes_count;   
    uint32_t s_first_data_block;    
    uint32_t s_log_block_size;     
    uint32_t s_inode_size;          
    uint32_t s_block_group_nr;      
    uint32_t s_feature_compat;      
    uint32_t s_feature_incompat;    
    uint32_t s_feature_ro_compat;   
};

// 定义块组描述符结构体
struct ext_group_desc {
    uint32_t bg_block_bitmap;      
    uint32_t bg_inode_bitmap;     
    uint32_t bg_inode_table;       
    uint16_t bg_free_blocks_count; 
    uint16_t bg_free_inodes_count; 
};

// 定义位图结构体
struct ext_bitmap {
    unsigned char *data;        
};

// 定义inode结构体
struct ext_inode {
    uint16_t    i_mode;     
    uint16_t    i_uid;      
    uint32_t    i_size;     
    uint32_t    i_atime;    
    uint32_t    i_ctime;    
    uint32_t    i_mtime;    
};

// 打印超级块信息
void print_super_block(struct ext_super_block *sb) {
    printf("超级块信息\n");
    printf("文件系统类型标识: %u\n", sb->s_feature_compat); 
    printf("文件系统大小: %u\n", sb->s_blocks_count); 
    printf("数据块大小: %u\n", 1024 << sb->s_log_block_size);  
    printf("inode大小: %u\n", sb->s_inode_size);  
    printf("块组大小: %u\n", sb->s_blocks_count / sb->s_block_group_nr);  
    printf("总块数: %u\n", sb->s_blocks_count);  
    printf("inode节点数: %u\n", sb->s_inodes_count); 
    printf("空闲块数: %u\n", sb->s_free_blocks_count);  
}

// 打印位图
void print_bitmap(int fd, uint32_t block_number, int block_size) {
    off_t offset = (off_t)block_number * block_size;
    unsigned char *bitmap = (unsigned char *)malloc(block_size);
    if (lseek(fd, offset, SEEK_SET) < 0 || read(fd, bitmap, block_size) < 0) {
        perror("Error reading bitmap");
        free(bitmap);
        return;
    }

    for (int i = 0; i < block_size; i++) {
        for (int j = 0; j < 8; j++) {
            if (bitmap[i] & (1 << j))
                printf("1");
            else
                printf("0");
        }
        printf(" ");
    }
    printf("\n");

    free(bitmap);
}

// 打印块组描述符信息
void print_group_desc(struct ext_group_desc *gd, int fd, int block_size) {
    printf("组描述符信息:\n");
    printf("块位图所在块号: %u\n", gd->bg_block_bitmap);  
    printf("inode位图所在块号: %u\n", gd->bg_inode_bitmap);  
    printf("inode表起始块号: %u\n", gd->bg_inode_table);  
    printf("空闲块数: %u\n", gd->bg_free_blocks_count);  
    printf("空闲inode数: %u\n", gd->bg_free_inodes_count);  

    printf("块位图信息:\n");
    print_bitmap(fd, gd->bg_block_bitmap, block_size);  

    printf("inode位图信息:\n");
    print_bitmap(fd, gd->bg_inode_bitmap, block_size);  
}

// 将时间戳转换为可读时间格式
void convert_timestamp(time_t timestamp, char* buffer, size_t buffer_size) {
    struct tm *timeinfo;
    timeinfo = localtime(&timestamp);
    strftime(buffer, buffer_size, "%Y-%m-%d %H:%M:%S", timeinfo);
}

// 打印inode信息
void print_inode(struct ext_inode *inode) {
    char buffer1[80];
    char buffer2[80];
    char buffer3[80];
    convert_timestamp(inode->i_atime, buffer1, sizeof(buffer1));  
    convert_timestamp(inode->i_ctime, buffer2, sizeof(buffer2));  
    convert_timestamp(inode->i_mtime, buffer3, sizeof(buffer3));  
    printf("inode数据项信息:\n");
    printf("文件模式: %u\n", inode->i_mode);  
    printf("用户ID: %u\n", inode->i_uid);  
    printf("文件大小: %u\n", inode->i_size); 
    printf("最后访问时间: %s\n", buffer1);  
    printf("创建时间: %s\n", buffer2);  
    printf("最后修改时间: %s\n", buffer3);  
}

// 主函数
int main(int argc, char **argv) {
    int fd;
    struct ext_super_block superblock;
    struct ext_group_desc group_desc;
    struct ext_inode inode;

    // 检查命令行参数是否正确
    if (argc != 2) {
        fprintf(stderr, "使用方法: %s <设备>\n", argv[0]);
        exit(1);
    }

    // 打开块设备
    fd = open(argv[1], O_RDONLY);
    if (fd < 0) {
        perror("无法打开块设备");
        exit(1);
    }

    // 设置偏移量到超级块位置
    off_t offset = 1024;
    if (lseek(fd, offset, SEEK_SET) < 0) {
        perror("lseek 错误");
        close(fd);
        exit(1);
    }

    // 读取超级块
    ssize_t bytes_read = read(fd, &superblock, sizeof(superblock));
    if (bytes_read < 0) {
        perror("读取超级块错误");
        close(fd);
        exit(1);
    }

    // 打印超级块信息
    print_super_block(&superblock);
    printf("\n");

    // 设置偏移量到组描述符位置
    offset += sizeof(superblock);
    if (lseek(fd, 4096, SEEK_SET) < 0) {
        perror("lseek 错误");
        close(fd);
        exit(1);
    }

    // 读取组描述符
    bytes_read = read(fd, &group_desc, sizeof(group_desc));
    if (bytes_read < 0) {
        perror("读取组描述符错误");
        close(fd);
        exit(1);
    }

    // 打印组描述符信息
    print_group_desc(&group_desc, fd, 1024 << superblock.s_log_block_size);
    printf("\n");

    // 设置偏移量到第一个inode的位置
    offset += sizeof(group_desc);
    if (lseek(fd, offset, SEEK_SET) < 0) {
        perror("lseek 错误");
        close(fd);
        exit(1);
    }

    // 读取第一个inode
    bytes_read = read(fd, &inode, sizeof(inode));
    if (bytes_read < 0) {
        perror("读取inode错误");
        close(fd);
        exit(1);
    }

    // 打印第一个inode信息
    print_inode(&inode);
    printf("\n");

    // 关闭文件描述符
    close(fd);

    return 0;
}

